<!-- 基础选人组件 -->

<!-- 属性 -->
<!-- 配置名称 | 类型 | 用途 | 返回值 | 默认值 | 必填 | 说明 -->
<!-- preset-people | Array<String> | 预置人员数据        | -            | []     | * | 无 -->
<!-- selected      | Array<String> | 已选择的人员        | -            | []     | - | 无 -->
<!-- multi         | Boolean       | 是否为多选          | -            | true   | - | 无 -->
<!-- data-api      | Function      | 获取人员数据Api     | Promise<any> | []     | * | 无 -->
<!-- key-name      | String        | 人员唯一标识的字段名 | -            | userId | * | 无 -->

<!-- 事件 -->
<!-- 无 -->

<!-- 插槽 -->
<!-- 无 -->

<!-- Expose -->
<!-- 方法名 | 说明 | 类型-->
<!-- getData    | 获取已选择的用户 | Array<any> -->
<!-- submitForm | 获取已选择的用户 | Array<any> -->
<script setup lang="ts">
import { ref } from 'vue'
import PersonSearch from './widgets/PersonSearch.vue'
import ModeSetting from './widgets/ModeSetting.vue'
import ModeAll from './widgets/ModeAll.vue'
import ModeDept from './widgets/ModeDept.vue'
import ModePreset from './widgets/ModePreset.vue'

interface Props {
  presetPeople?: any[]
  selected?: any[]
  multi?: boolean
  dataApi?: (option?: any) => Promise<any>
  keyName?: string
}

const props = withDefaults(defineProps<Props>(), {
  presetPeople: () => {
    return []
  },
  selected: () => {
    return []
  },
  multi: true,
  dataApi: () => {
    return new Promise((resolve) => {
      resolve([])
    })
  },
  keyName: 'userId'
})

const mode = ref('all')
if (props.presetPeople?.length) {
  mode.value = 'preset'
}

const modeAllRef = ref()
const modePresetRef = ref()
const modeDeptRef = ref()

// 新增人员
const addData = ref<any[]>([])

const handlePersonChange = (checked: boolean, person: any) => {
  if (checked) {
    // 选中
    addData.value.push({
      ...person
    })
  } else {
    // 取消
    addData.value = addData.value.filter((item: any) => item[props.keyName] !== person[props.keyName])
  }
}

const handlePersonPick = (person: any) => {
  addData.value = [
    {
      ...person
    }
  ]
}

const handlePersonRemove = (person: any) => {
  // 从新增人员中删除
  addData.value = addData.value.filter((item: any) => item[props.keyName] !== person[props.keyName])
  switch (mode.value) {
    case 'preset':
      modePresetRef.value.toggle(false, person)
      break
    case 'all':
      modeAllRef.value.toggle(false, person)
      break
    case 'dept':
      modeDeptRef.value.toggle(false, person)
      break
    default:
      break
  }
}

const handlePersonCheck = (person: any) => {
  addData.value.push(person)
  switch (mode.value) {
    case 'preset':
      modePresetRef.value.toggle(true, person)
      break
    case 'all':
      modeAllRef.value.toggle(true, person)
      break
    case 'dept':
      modeDeptRef.value.toggle(true, person)
      break
    default:
      break
  }
}

const handleSearchPick = (person: any) => {
  if (props.multi) {
    // 是否在已选人员中
    const target4Selected = props.selected.find((item: any) => item[props.keyName] === person[props.keyName])
    if (target4Selected) {
      return
    }
    // 是否在新增人员中
    const target = addData.value.find((item: any) => item[props.keyName] === person[props.keyName])
    if (target) {
      // 如果在，则取消
      handlePersonRemove(person)
    } else {
      // 如果不在，则勾选
      handlePersonCheck(person)
    }
  } else {
    // 是否在已选人员中
    const target4Selected = props.selected.find((item: any) => item[props.keyName] === person[props.keyName])
    if (target4Selected) {
      return
    }
    handlePersonPick(person)
    switch (mode.value) {
      case 'preset':
        modePresetRef.value.pick(person)
        break
      case 'all':
        modeAllRef.value.pick(person)
        break
      case 'dept':
        modeDeptRef.value.pick(person)
        break
      default:
        break
    }
  }
}

const getData = () => {
  const result = addData.value.map((item: any) => {
    return {
      ...item,
      keyValue: item[props.keyName]
    }
  })
  return result
}

const submitForm = () => {
  return getData()
}

defineExpose({
  getData,
  submitForm
})
</script>

<template>
  <div class="base-person-select-wrapper">
    <div class="base-person-select-panel">
      <PersonSearch :preset-people="props.presetPeople" :data-api="props.dataApi" @pick="handleSearchPick"></PersonSearch>
      <ModeSetting v-if="mode !== 'preset'" v-model="mode"></ModeSetting>
      <div class="scroll-box">
        <ModePreset
          v-if="mode === 'preset'"
          ref="modePresetRef"
          :multi="props.multi"
          :preset-people="props.presetPeople"
          :selected="props.selected"
          :picked="addData"
          @change="handlePersonChange"
          @pick="handlePersonPick"
        ></ModePreset>
        <ModeAll
          v-if="mode === 'all'"
          ref="modeAllRef"
          :multi="props.multi"
          :data-api="props.dataApi"
          :selected="props.selected"
          :picked="addData"
          @change="handlePersonChange"
          @pick="handlePersonPick"
        ></ModeAll>
        <ModeDept v-if="mode === 'dept'" ref="modeDeptRef"></ModeDept>
      </div>
    </div>
    <div class="base-person-select-panel panel-border">
      <div class="count-box">已选成员 {{ addData.length }} 位</div>
      <div class="scroll-box">
        <div class="add-data-container">
          <div v-for="item in addData" :key="item[props.keyName]" class="person-item">
            <el-tag
              size="large"
              :closable="props.multi"
              @close="
                () => {
                  handlePersonRemove(item)
                }
              "
            >
              {{ `${item.userName}${item.extra ? `(${item.extra})` : ''}` }}
            </el-tag>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.base-person-select-wrapper {
  @include rect(800px, 500px);
  box-sizing: border-box;
  padding: 20px;
  display: flex;
  .base-person-select-panel {
    @include rect(50%, 100%);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    &.panel-border {
      border-left: 1px solid rgb(220, 223, 230);
      padding-left: 20px;
      .count-box {
        font-weight: bold;
        margin-bottom: 20px;
      }
    }
    .scroll-box {
      width: 100%;
      flex: 1;
      overflow: auto;
      .add-data-container {
        display: flex;
        flex-wrap: wrap;
        .person-item {
          margin-right: 10px;
          margin-bottom: 10px;
        }
      }
    }
  }
}
</style>
